FlowViz

Renderer

function
Renderer()

Option name Type Description
viz object A d3 selection for the root node of the visualization
config ConfigParser The config parser object

The Renderer module is responsible for rendering to the screen the list of nodes and edges provided by the
GraphManager module.

function Renderer(flowviz) {
    fv = flowviz;

    // Create the d3 utility function for drawing lines
    this.DrawLine = d3.svg.line()
        .x(function(d) {return d.x;})
        .y(function(d) {return d.y;})
        .interpolate('monotone');

    // Create the d3 drag behavior
    drag = d3.behavior.drag().origin(function(d) { return d; });
    fv.Interactions.SetupInteractions(drag,["Drag"]);

    // Initialize the renderer
    this._Initialize();
    this.IsReinitializing = false;

    //Objects for referencing the node and edge lists
    this.n = null;
    this.e = null;
}

Renderer.prototype._Initialize = function() {
    var viz = d3.select(fv.Selector);

    //Draw the edge layer below the node layer
    this.edges = viz.append('g')
        .attr('id', 'edge-group');

    this.nodes = viz.append('g')
        .attr('id', 'node-group');
};

Private Section


DrawNode

function
DrawNode()

Option name Type Description
d FlowNode The current node in a d3 selection
i number The index of the current node

Draws a node by obtaining the svg description from the node's type and appending it to the node's location in the
DOM scenegraph.

function DrawNode(d, i) {
    var s = Snap('g#flow-node-' + i);

    var svg = d.type.getSvg();
    svg.attr('transform', 'scale(' + d.type.scale + ')');
    svg.attr('class', 'node-background');
    s.append(svg);

    var svg2 = d.type.getSvg();
    svg2.attr('transform', 'scale(' + d.type.scale + ')');
    s.append(svg2);
}

DrawEdgePath

function
DrawEdgePath()

Option name Type Description
d object d3 data object
i object d3 data object index

Draws the path of an edge between two nodes.

function DrawEdgePath(d, i) {
    d.setSvgPath(fv.Renderer.DrawLine(d.getPath()));

    d3.select('path#flow-edge-path-' + i)
        .attr('d', d.getSvgPath())
        .attr('class', 'flow-edge-path');
}

DrawEdgeRegion

function
DrawEdgeRegion()

Option name Type Description
d FlowEdge Current FlowEdge object
i number Data item index

Draws a larger invisible region over an edge so that the edge can be interacted with

function DrawEdgeRegion(d, i) {
    d3.select('path#flow-edge-region-' + i)
        .attr('d', d.getSvgPath())
        .attr('class', 'flow-edge-region')
        .call(fv.Interactions.SetupInteractions, ["EdgeRegion"]);
}

DrawEdgeTips

function
DrawEdgeTips()

Option name Type Description
d FlowNode d3 data object
i number d3 data object index

Draws the forward tip on an edge.

In the previous version, this could either have been arrow heads in the forward and/or backward directions, or dots
indicating no direction. In the current version, only forward arrows are allowed.

function DrawEdgeTips(d, i) {
    d3.select('g#flow-edge-tip-' + i)
        .append('path')
        .attr('d', fv.Renderer.DrawLine(d.getForwardTip()))
        .attr('class', 'flow-edge-tip forward');
}

UpdateEdges

function
UpdateEdges()

Option name Type Description
updateSet Array A d3 selection of all of the edges in the edge layer

Updates all of the edges in the update set.

function UpdateEdges(updateSet) {
    // Update edge paths
    updateSet.selectAll('path.flow-edge-path')
        .each(function(d) {d.setSvgPath(fv.Renderer.DrawLine(d.getPath()));})
        .attr('d', function(d) {return d.getSvgPath();});

    updateSet.selectAll('path.flow-edge-region')
        .attr('d', function(d) {return d.getSvgPath();});

    // Update tips (arrow heads)
    updateSet.selectAll('g g path.forward')
        .attr('d', function(d) {return fv.Renderer.DrawLine(d.getForwardTip());});
}

drag

declaration
drag

A d3 behavior which enables the ability to drag nodes in the graph.

var drag = null;

Public Section


SetNodeListRef

method
Renderer.prototype.SetNodeListRef()

Option name Type Description
list object A list of the nodes

Sets this object's reference to the GraphManager's list of nodes. This should only be called once: in the
GraphManager's constructor!

Renderer.prototype.SetNodeListRef = function(list) {
    this.n = list;
};

SetEdgeListRef

method
Renderer.prototype.SetEdgeListRef()

Option name Type Description
list object A list of the edges

Sets this object's reference to the GraphManager's list of edges. This should only be called once: in the
GraphManager's constructor!

Renderer.prototype.SetEdgeListRef = function(list) {
    this.e = list;
};

RenderEdges

method
Renderer.prototype.RenderEdges()

Updates, creates, and removes edges.

Renderer.prototype.RenderEdges = function() {
    // Get the update set
    var edges = this.edges
        .selectAll('g.flow-edge')
        .data(this.e);

    // Run updates
    UpdateEdges(edges);

    // Exit set
    edges.exit().remove();

    // Enter Set
    var arrow = edges.enter()
        .append('g')
        .attr('class', 'flow-edge');

    arrow.append('path')
        .attr('id', function(d, i) {return 'flow-edge-path-' + i;})
        .each(DrawEdgePath);

    arrow.append('path')
        .attr('id', function(d, i) {return 'flow-edge-region-' + i;})
        .each(DrawEdgeRegion);

    arrow.append('g')
        .attr('id', function(d, i) {return 'flow-edge-tip-' + i;})
        .each(DrawEdgeTips);
};

RenderNodes

method
Renderer.prototype.RenderNodes()

Updates, creates, and removes nodes.

Renderer.prototype.RenderNodes = function() {
    // Selection
    var nodes = this.nodes
        .selectAll('g.flow-node')
        .data(this.n);

    // Update set
    nodes.attr('transform', function(d) {
        return 'translate(' + d.x + ',' + d.y + ')';
    });

    // Exit set
    nodes.exit().remove();

    // Enter Set
    var node = nodes.enter()
        .append('g')
        .attr('class', 'flow-node')
        .attr('id', function(d, i) {return 'flow-node-' + i;})
        .attr('transform', function(d) {return 'translate(' + d.x + ',' + d.y + ')';})
        .call(fv.Interactions.SetupInteractions, ["Node"])
        .each(DrawNode);

    if(fv.Config.draggable) {
        node.call(drag);
    }
};

Update

method
Renderer.prototype.Update()

The main rendering function. This function renders the graph to the screen and updates the previously rendered
version of the graph.

Renderer.prototype.Update = function() {
    this.RenderEdges();
    this.RenderNodes();

    if(this.IsReinitializing) {
        this.IsReinitializing = false;
        fv.emit('renderer-redrawn');
    } else {
        fv.emit('renderer-updated');
    }
};

Reinitialize

method
Renderer.prototype.Reinitialize()

Begins the process of completely redrawing the visualization by reinitializing the scenegraph. Note that after calling
this, new data may be added, and then Renderer.Update() must be called to actually draw the visualization.

Renderer.prototype.Reinitialize = function() {
    fv.Selection.Clear();

    d3.select(fv.Selector).selectAll('g').remove();

    this._Initialize();

    this.IsReinitializing = true;
};

RedrawEdges

method
Renderer.prototype.RedrawEdges()

Method for redrawing edges in the event that any property of the edge needs to change other than the start and end
positions.

Renderer.prototype.RedrawEdges = function() {
    d3.selectAll('g.flow-edge').remove();
    this.RenderEdges();
};

DrawConnection

method
Renderer.prototype.DrawConnection()

Option name Type Description
tmpNode FlowNode A dummy node used for tracking the current mouse location
tmpEdge FlowEdge The edge that is being created

Updates the temporary node and edge that are used for depicting the creation of new edges in the graph

Renderer.prototype.DrawConnection = function(tmpNode, tmpEdge) {
    this.edges
        .append('g')
        .datum(tmpEdge)
        .attr('class', 'flow-edge-temp')
        .append('path')
        .attr('class', 'flow-edge-tmp-path')
        .attr('d', function(d) {
            return fv.Renderer.DrawLine(d.getPath());
        })
        .attr('stroke-dasharray', '5,5')
        .attr('stroke', 'black')
        .attr('stroke-width', 3)
        .attr('fill', 'none');

    // Enter Set
    this.nodes
        .append('g')
        .datum(tmpNode)
        .attr('class', 'flow-node-temp')
        .attr('transform', function(d) {return 'translate(' + d.x + ',' + d.y + ')';})
        .each(function(d) {
            fv.Interactions.SetupInteractions($(document), ["NewEdge"]);
        });

    // Remove the normal click listener
    fv.Interactions.Clear(d3.selectAll('g.flow-node'), ["Node"]);

    // Only allow connections to end on other pre-existing nodes
    fv.Interactions.SetupInteractions(d3.selectAll('g.flow-node'), ["CreateEdge"]);

};

RemoveTempListeners

method
Renderer.prototype.RemoveTempListeners()

Removes the event listeners that are involved in the process of generating new edges in the graph.

Renderer.prototype.RemoveTempListeners = function() {
    $(document).off('click');

    // Remove the temp click listener
    fv.Interactions.Clear(d3.selectAll('g.flow-node'), ["Node"]);

    // Add the normal click listener back
    fv.Interactions.SetupInteractions(d3.selectAll('g.flow-node'), ["Node"]);
};

RemoveTempParts

method
Renderer.prototype.RemoveTempParts()

Removes the temporary node and edge that are added to the graph when a new edge is being created.

Renderer.prototype.RemoveTempParts = function() {
    this.edges
        .select('g.flow-edge-temp')
        .remove();

    this.nodes
        .select('g.flow-node-temp')
        .remove();
};